home *** CD-ROM | disk | FTP | other *** search
/ CD Ware Multimedia 1994 November / Cd Ware (Nro. 2) - Epimundo.iso / OS2 / PC2_170.ZIP / SOURCE.ZIP / Source / PC2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-01  |  96.1 KB  |  1,727 lines

  1. /***********************************************************************\
  2.  *                                PC2.c                                *
  3.  *              Copyright (C) by Stangl Roman, 1993, 1994              *
  4.  * This Code may be freely distributed, provided the Copyright isn't   *
  5.  * removed, under the conditions indicated in the documentation.       *
  6.  *                                                                     *
  7.  * PC/2 - Program Commander/2 is a configurable program starter for    *
  8.  * OS/2 2.x PM. If the user clicks button 1 on the DESKTOP, a user     *
  9.  * modifyable popup menu is displayed. The user then selects a program *
  10.  * to be started, or configuration of PC/2 or dismisses it.            *
  11.  * You can define Hotkeys to switch to a program, or start it if it is *
  12.  * not already running.                                                *
  13.  * PC/2 is an alternative method of starting programs compared to      *
  14.  * icons and uses no space on DESKTOP, and no folder must be opended   *
  15.  * to start a program. For frequently used programs, this reduces the  *
  16.  * time to start an application.                                       *
  17.  * PC/2 also implements an optional virtual Desktop and sliding focus. *
  18.  *                                                                     *
  19. \***********************************************************************/
  20.  
  21. static char RCSID[]="@(#) $Header: PC2.c/PC2.h Version 1.70 06,1994 $ (LBL)";
  22.  
  23. #define         _FILE_  "PC/2 - PC2.c V1.70"
  24.  
  25. #include        "PC2.h"                 /* User include files */
  26. #include        "Error.h"
  27.  
  28. HEV             hevPc2;                 /* Handle of PC/2 semaphore */
  29. BOOL            InstallHelp;            /* True if we're installing */
  30. UCHAR           *pucFilenameProfile;    /* The buffer holding the filename of the profile */
  31. UCHAR           *pucFilenameINI;        /* Path and filename of PC2.INI */
  32. UCHAR           *pucFilenameHLP;        /* The buffer holding the filename of the HLP file */
  33. HMODULE         hDllPc2;                /* Handle of PC/2 DLL */
  34. TID             tidThread;              /* Working thread ID */
  35. /*                                                                                      *\
  36.  * Reserve data referenced generally through all modules. This isn't the best way, hope *
  37.  * that I have time to port to C++...                                                   *
  38. \*                                                                                      */
  39. HAB             hab;                    /* Handle of PM anchor block */
  40. HMQ             hmq;                    /* Handle of message queue */
  41. HWND            hwndFrame;              /* Frame handle of window */
  42. HWND            hwndClient;             /* Client handle of window */
  43. HWND            hwndPopupMenu;          /* Handel of popup menu window */
  44.                                         /* Input options: mouse button 1 depressed,
  45.                                            Input devices keyboard or mouse button 1,
  46.                                            popup menu allways visible on DESKTOP,
  47.                                            position so that ID_CONFIGDIALOG is under the
  48.                                            pointer */
  49. HWND            hwndHelp;               /* Help window handle */
  50. SESSIONDATA     SessionData;            /* Used by Menu Installation dialog and by
  51.                                            Program Installation dialog to store menu or
  52.                                            program data, to be filled from the user or
  53.                                            to be presented to the user. */
  54. MENUDATA        *pPopupMenu=NULL;       /* Used by all procedures as the starting point
  55.                                            of a linked list of menu entries. */
  56. MENUDATA        *pMenuData;             /* This pointer points to the current level of
  57.                                            Submenus and Menuitems within the configuration
  58.                                            dialog procedure */
  59.                                         /* Create linked list by starting with this ID */
  60. USHORT          MenuDataId=ID_POPUPMENU;
  61. USHORT          DialogResult;           /* Each dialog procedure returns the result in
  62.                                            this variable to enable the calling routine to
  63.                                            check, if there is valid data or not. */
  64. FILE            *Pc2Profile;            /* Open the profile, where the user entered menu
  65.                                            data is stored, with this handle */
  66. SWP             swpScreen;              /* The screen dimensions */
  67. BOOL            bConfigDialog=FALSE;    /* TRUE only if the Configuration dialog exists */
  68. WINDOWS         Windows;                /* All windows on PM are traced in this structure */
  69.  
  70. /*--------------------------------------------------------------------------------------*\
  71.  * The main procedure.                                                                  *
  72.  * Req:                                                                                 *
  73.  *      argc, argv, envp                                                                *
  74.  * Returns:                                                                             *
  75.  *      int ........... Exitcode (0, or errorlevel)                                     *
  76. \*--------------------------------------------------------------------------------------*/
  77. int main(int argc, char *argv[], char *envp[])
  78. {
  79. QMSG    qmsg;                           /* Message queue */
  80. ULONG   counter;                        /* Temporary counter */
  81.                                         /* Frame creation control flag */
  82. ULONG   flCreate=FCF_ICON | FCF_SIZEBORDER | FCF_TASKLIST | FCF_MENU | FCF_TITLEBAR | FCF_HIDEBUTTON | FCF_ACCELTABLE;
  83.  
  84.                                         /* Default the Popup-Menu is displayed after a
  85.                                            WM_BUTTON1DBLCLK on the Desktop, but users may
  86.                                            prefer WM_BUTTON1CLICK to popup the menu */
  87. HookParameters.ulClickFlag=WM_BUTTON1DBLCLK;
  88. /*                                                                                      *\
  89.  * Get the full path and filename of the running copy of PC/2 and change the extension  *
  90.  * .EXE into .cfg to open the configuration file under this name. If the user supplies  *
  91.  * [-,/Profile filename.ext] then use this filename as the Profile. Also change .EXE    *
  92.  * into .HLP, .INI and PC/2 directory as the current directory to access .DLL.          *
  93. \*                                                                                      */
  94.                                         /* Long enough to hold user Profile name */
  95. pucFilenameProfile=malloc(strlen(argv[0])+64);
  96. pucFilenameINI=malloc(strlen(argv[0])+1);
  97. pucFilenameHLP=malloc(strlen(argv[0])+1);
  98. strcpy(pucFilenameProfile, argv[0]);
  99. strcpy(pucFilenameINI, argv[0]);
  100. strcpy(pucFilenameHLP, argv[0]);
  101. strcpy(strchr(pucFilenameProfile, '.'), ".cfg");
  102. strcpy(strchr(pucFilenameINI, '.'), ".ini");
  103. strcpy(strchr(pucFilenameHLP, '.'), ".hlp");
  104. InstallHelp=FALSE;                      /* Assume no installation */
  105. for(counter=1; counter<argc; counter++)
  106.     {
  107.     strupr(argv[counter]);              /* Convert to uppercase */
  108.                                         /* Test for /PROFILE or -PROFILE to get a
  109.                                            profile name */
  110.     if((strstr(argv[counter], "/PROFILE")!=NULL) ||
  111.         (strstr(argv[counter], "-PROFILE")!=NULL))
  112.         strcpy((pucFilenameProfile+strlen(pucFilenameProfile)-7), argv[counter+1]);
  113.                                         /* Test for /INSTALL or -INSTALL to start the help
  114.                                            panels during initialization */
  115.     if((strstr(argv[counter], "/INSTALL")!=NULL) ||
  116.         (strstr(argv[counter], "-INSTALL")!=NULL))
  117.         InstallHelp=TRUE;
  118.                                         /* Test for /DOUBLECLICK or -DOUBLECLICK to display
  119.                                            the Popup-Menu after a double-click instead of
  120.                                            a single click */
  121.     if((strstr(argv[counter], "/DOUBLECLICK")!=NULL) ||
  122.         (strstr(argv[counter], "-DOUBLECLICK")!=NULL))
  123.         HookParameters.ulClickFlag=WM_BUTTON1DBLCLK;
  124.                                         /* Test for /SINGLECLICK or -SINGLECLICK to display
  125.                                            the Popup-Menu after a double-click instead of
  126.                                            a single click */
  127.     if((strstr(argv[counter], "/SINGLECLICK")!=NULL) ||
  128.         (strstr(argv[counter], "-SINGLECLICK")!=NULL))
  129.         HookParameters.ulClickFlag=WM_BUTTON1CLICK;
  130.     }
  131. INIAccess(pucFilenameINI, TRUE);        /* Get data from PC2.INI into HookParameters */
  132. do
  133. {
  134.                                         /* Initialize anchor block and message queue */
  135.     if(WinStartUp(&hab, &hmq)==FALSE) break;
  136.     HookParameters.habWindow=hab;       /* Save anchor block handle */
  137.     if(!WinRegisterClass(               /* Register window class */
  138.         hab,                            /* Handle of anchor block */
  139.         (PSZ)PC2_CLASSNAME,             /* Window class name */
  140.         (PFNWP)PC2_MainWindowProc,      /* Address of window procedure */
  141.                                         /* Class style */
  142.         CS_SIZEREDRAW | CS_SAVEBITS | CS_MOVENOTIFY,
  143.         0))                             /* Extra window words */
  144.         {
  145.         GEN_ERR(hab, (HWND)NULL, (HWND)NULL);
  146.         break;
  147.         }
  148. /*                                                                                      *\
  149.  * Check if we are allready loaded before by querying a semaphore that is defined the   *
  150.  * first time PC/2 runs.                                                                *
  151. \*                                                                                      */
  152.     if(DosCreateEventSem(               /* Create a semaphore */
  153.         PC2_SEM,                        /* Name */
  154.         &hevPc2,                        /* Handle */
  155.         (ULONG)0,                       /* Named semaphores are allways shared */
  156.         (BOOL32)FALSE))                 /* Initially set */
  157.         {                               /* If an error occurs, either we can't create
  158.                                            the semaphore or it allready exists. We assume
  159.                                            that it exists, meaning PC/2 allready loaded.
  160.                                            Parameters NULL force an immediate exit(1). */
  161.         USR_ERR("PC/2 already loaded - exiting...", (HWND)NULL, (HWND)NULL);
  162.         break;                          /* Not needed but for safety... */
  163.         }
  164. /*                                                                                      *\
  165.  * Now get device resolution and save it and other initilization data to the structure  *
  166.  * used to communicate with PC2HOOK.DLL.                                                *
  167. \*                                                                                      */
  168.                                         /* Query and save the device resolution, f.e.
  169.                                            1024 * 768 */
  170.     swpScreen.cx=WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN);
  171.     swpScreen.cy=WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN);
  172.                                         /* Now initialized the virtual Desktop data */
  173.     HookParameters.DesktopSize.x=swpScreen.cx;
  174.     HookParameters.DesktopSize.y=swpScreen.cy;
  175.     HookParameters.LLHotBorder.x=HookParameters.DesktopSize.x*0.15;
  176.     HookParameters.LLHotBorder.y=HookParameters.DesktopSize.y*0.15;
  177.     HookParameters.URHotBorder.x=HookParameters.DesktopSize.x*0.85;
  178.     HookParameters.URHotBorder.y=HookParameters.DesktopSize.y*0.85;
  179.     HookParameters.VirtualDesktopPos.x=0;
  180.     HookParameters.VirtualDesktopPos.y=0;
  181.     HookParameters.VirtualDesktopMin.x=-swpScreen.cx;
  182.     HookParameters.VirtualDesktopMin.y=-swpScreen.cy;
  183.     HookParameters.VirtualDesktopMax.x=swpScreen.cx;
  184.     HookParameters.VirtualDesktopMax.y=swpScreen.cy;
  185.     HookParameters.SlidingXFactor=(HookParameters.ulScrollPercentage*
  186.         HookParameters.DesktopSize.x)/100;
  187.     HookParameters.SlidingYFactor=(HookParameters.ulScrollPercentage*
  188.         HookParameters.DesktopSize.y)/100;
  189.     HookParameters.hwndDesktop=0;       /* Initialize to a value not used by PM (hopefully) */
  190.     HookParameters.hwndWPS=0;
  191. /*                                                                                      *\
  192.  * Pc2Hook.dll is already loaded from the directory PC/2 was started from or via the    *
  193.  * LIBPATH. We just need to query the handle.                                           *
  194. \*                                                                                      */
  195.     if(DosQueryModuleHandle(            /* Get the module handle of a DLL that was previously loaded */
  196.         "PC2Hook",                      /* ASCIIZ name of the DLL */
  197.         &hDllPc2)!=NO_ERROR)            /* DLL handle returned */
  198.         {
  199.         USR_ERR("Can't determine module handle of PC2HOOK.DLL - exiting...", HWND_DESKTOP, HWND_DESKTOP);
  200.         break;
  201.         }
  202.     PC2DLL_SetParameters();             /* Initialize data in PC2Hook DLL */
  203. /*                                                                                      *\
  204.  * Start frame window, which creates window(s) and WM_CREATE message.                   *
  205. \*                                                                                      */
  206.     if((hwndFrame=WinCreateStdWindow(   /* Create a standard window */
  207.         HWND_DESKTOP,                   /* DESKTOP is parent */
  208.         0,                              /* Standard window styles */
  209.         &flCreate,                      /* Frame control flags */
  210.         (PSZ)PC2_CLASSNAME,             /* Client window class name */
  211.         "",                             /* No window text */
  212.         0,                              /* No special class style */
  213.         (HMODULE)0,                     /* Ressource is in .EXE file */
  214.         ID_PC2MAINWINDOW,               /* Frame window identifier */
  215.         &hwndClient)                    /* Client window handle */
  216.         )==NULLHANDLE)
  217.         {
  218.         GEN_ERR(hab, (HWND)NULL, (HWND)NULL);
  219.         break;
  220.         }
  221.     HookParameters.hwndPC2=hwndClient;  /* Save window handle to send message to display
  222.                                            the Popup-Menu */
  223. /*                                                                                      *\
  224.  * Now initilize Help, if it can't be initialized the we get no help but that's no      *
  225.  * reason to terminate.                                                                 *
  226. \*                                                                                      */
  227.     if(WinStartHelp(hab, pucFilenameHLP, &hwndHelp)==FALSE)
  228.         USR_ERR("Can't find PC2.HLP, please check HLP file and HELP - ignoring help requests...",
  229.             hwndFrame, hwndClient);
  230. /*                                                                                      *\
  231.  * Set text to titlebar and size & position. Ensure that position is limited.           *
  232. \*                                                                                      */
  233.     if((HookParameters.swpPC2.x<HookParameters.VirtualDesktopMin.x) ||
  234.         (HookParameters.swpPC2.x>HookParameters.VirtualDesktopMax.x))
  235.         HookParameters.swpPC2.x=8;
  236.     if((HookParameters.swpPC2.y<HookParameters.VirtualDesktopMin.y) ||
  237.         (HookParameters.swpPC2.y>HookParameters.VirtualDesktopMax.y))
  238.         HookParameters.swpPC2.y=8;
  239.     if(HookParameters.swpPC2.cx>HookParameters.DesktopSize.x)
  240.         HookParameters.swpPC2.cx=256;
  241.     if(HookParameters.swpPC2.cy>HookParameters.DesktopSize.y)
  242.         HookParameters.swpPC2.cy=192;
  243.     WinSetWindowText(hwndFrame, "PC/2");
  244.     if(!WinSetWindowPos(                /* Set window postion */
  245.         hwndFrame,                      /* Window handle */
  246.         HWND_BOTTOM,
  247.         HookParameters.swpPC2.x,
  248.         HookParameters.swpPC2.y,
  249.         HookParameters.swpPC2.cx,
  250.         HookParameters.swpPC2.cy,
  251.         SWP_HIDE | SWP_MOVE | SWP_SIZE | SWP_DEACTIVATE))
  252.         GEN_ERR(hab, (HWND)NULL, (HWND)NULL);
  253.                                         /* Display overview window if requested */
  254.     if(HookParameters.ulStatusFlag & OVERVIEW)
  255.         WinSetWindowPos(hwndFrame, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER | SWP_SHOW | SWP_DEACTIVATE);
  256. /*                                                                                      *\
  257.  * Now setup the Popup-Menu by loading the data from the profile and install the hook   *
  258.  * into the system input queue.                                                         *
  259. \*                                                                                      */
  260.     hwndPopupMenu=WinLoadMenu(          /* Load popup menu */
  261.         hwndClient,                     /* Owner window handle */
  262.         (HMODULE)0,                     /* Ressource in .EXE file */
  263.         ID_PC2POPUPMENU);               /* Menu identifier in ressource file */
  264.                                         /* Load the data from the profile */
  265.     WinPostMsg(hwndClient, WM_SETPOPUPMENU, NULL, NULL);
  266.                                         /* Now install the hook */
  267.     WinPostMsg(hwndClient, WM_LOADHOOK, NULL, NULL);
  268. /*                                                                                      *\
  269.  * Here we loop dispatching the messages...                                             *
  270. \*                                                                                      */
  271.     while(WinGetMsg(hab, &qmsg, 0, 0, 0))
  272.         WinDispatchMsg(hab, &qmsg);     /* Dispatch messages to window procedure */
  273.     WinDestroyWindow(hwndFrame);        /* Close window */
  274. } while (FALSE);
  275.  
  276. if(WinCloseDown(&hwndHelp, &hab, &hmq)==FALSE)
  277.     {
  278.                                         /* Wait for working thread to close */
  279.     DosWaitThread(&tidThread, DCWW_WAIT);
  280.     return(1);
  281.     }
  282. else
  283.     {
  284.                                         /* Wait for working thread to close */
  285.     DosWaitThread(&tidThread, DCWW_WAIT);
  286.     return(0);
  287.     }
  288. }
  289.  
  290. /*--------------------------------------------------------------------------------------*\
  291.  * This procedure is the PC/2 window procedure.                                         *
  292. \*--------------------------------------------------------------------------------------*/
  293. MRESULT EXPENTRY PC2_MainWindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  294. {
  295. static USHORT   usMenuCommand;          /* Last message from smarticons */
  296. static HPOINTER hPointerMove;           /* Pointer when moving windows on overview window */
  297. static HPOINTER hPointerAction;         /* Pointer when performing the other actions on windows */
  298. static HWND     hwndMenu;               /* PC/2's menu window handle */
  299.  
  300. switch(msg)
  301. {
  302. case WM_CREATE:                         /* Create window by WinCreateStdWindow() */
  303.     {
  304.                                         /* First call default window procedure */
  305.     WinDefWindowProc(hwnd, msg, mp1, mp2);
  306.                                         /* Load pointers from resource */
  307.     hPointerMove=WinLoadPointer(HWND_DESKTOP, NULLHANDLE, ID_MOVEPOINTER);
  308.     hPointerAction=WinLoadPointer(HWND_DESKTOP, NULLHANDLE, ID_ACTIONPOINTER);
  309.     usMenuCommand=ID_ICONMOVE;          /* Setup smarticon's control */
  310.     Windows.ulDesktop=(ULONG)-1;        /* Set to -1 because currently we don't know Desktop's name */
  311.     Windows.ulWindowList=(ULONG)-1;     /* Set to -1 because currently we don't know Window List's name */
  312.     if(InstallHelp==TRUE)               /* For installation display help panels */
  313.         WinPostMsg(hwnd, WM_COMMAND, MPFROMSHORT(ID_HELP), NULL);
  314.                                         /* Start working thread */
  315.     tidThread=_beginthread(PC2_Thread, NULL, 65536, NULL);
  316.     if(tidThread==(TID)-1)
  317.         {
  318.         USR_ERR("Can't start working thread - exiting...",
  319.             hwndFrame, hwndClient);
  320.                                         /* Post exit message */
  321.         WinPostMsg(hwnd, WM_QUIT, NULL, NULL);
  322.         }
  323.     }
  324.     break;
  325.  
  326. case WM_PAINT:                          /* Draw overview of virtual Desktop */
  327.     {
  328.     HPS         hpsClient;
  329.                                         /* Get a cached presentation space */
  330.     hpsClient=WinBeginPaint(hwnd, NULLHANDLE, NULL);
  331.                                         /* Request repaint from working thread */
  332.     WinPostMsg(hwndThread, WM_REPAINT, NULL, NULL);
  333.     WinEndPaint(hpsClient);
  334.     }
  335.     break;
  336.  
  337. /*                                                                                      *\
  338.  * Syntax: WM_SETPOPUPMENU, NULL, NULL                                                  *
  339. \*                                                                                      */
  340. case WM_SETPOPUPMENU:
  341. /*                                                                                      *\
  342.  * Open the profile for reading the linked list containing the popup menu data. If the  *
  343.  * profile can't be opened, the file is assumed to be empty so the popup menu is empty. *
  344. \*                                                                                      */
  345.     if((Pc2Profile=fopen(pucFilenameProfile, "r"))==NULL)
  346.         {
  347.         pPopupMenu=AllocateMenuData();  /* Allocate an empty MENUDATA structure used as
  348.                                            the first element of linked list */
  349.         USR_ERR("Cannot open confguration file - assuming empty file", hwndFrame, hwndClient);
  350.         }
  351.     else
  352.         {
  353.         static UCHAR    Buffer[256];
  354.  
  355.         bConfigDialog=FALSE;            /* Assume the Configuration Dialog isn't part
  356.                                            of the profile */
  357.         pPopupMenu=AllocateMenuData();  /* Allocate an empty MENUDATA structure used as
  358.                                            the first element of linked list */
  359.         fgets(Buffer, sizeof(Buffer), Pc2Profile);
  360.         if(strcmp(Buffer, "PROFILE START\n")==0)
  361.             LoadMenu(pPopupMenu);       /* Load the rest by calling a recursive procedure */
  362.         fclose(Pc2Profile);
  363.         }
  364.     pMenuData=pPopupMenu;               /* Initialize *MENUDATA for Configuration dialog
  365.                                            procedure to a known value */
  366.     break;
  367.  
  368. /*                                                                                      *\
  369.  * Syntax: WM_LOADHOOK, NULL, NULL                                                      *
  370. \*                                                                                      */
  371. case WM_LOADHOOK:
  372. /*                                                                                      *\
  373.  * Install the hook into the system input queue pointing to the PC2DLL_Hook() procedure *
  374.  * in the DLL PC2HOOK.DLL. If we can't do this we exit after an error message box.      *
  375. \*                                                                                      */
  376.                                         /* Query and set the window handle of the Desktop */
  377.     WinSendMsg(hwnd, WM_SETDESKTOPHANDLE, NULL, NULL);
  378.     if(WinSetHook(                      /* Set a hook */
  379.         hab,                            /* Handle of anchor block */
  380.         NULLHANDLE,                     /* Hook into system message queue */
  381.         HK_INPUT,                       /* Hook of system input queue */
  382.         (PFN)PC2DLL_Hook,               /* Pointer to hook procedure */
  383.         hDllPc2)==FALSE)
  384.         {
  385.         USR_ERR("Hooking the system input queue failed - exiting...", hwndFrame, hwndClient);
  386.         WinPostMsg(hwnd, WM_QUIT, NULL, NULL);
  387.         }
  388.     break;
  389.  
  390. /*                                                                                      *\
  391.  * Syntax: WM_DESKTOPMOVE, LONG SlidingXFactor, LONG SlidingYFactor                     *
  392. \*                                                                                      */
  393. case WM_DESKTOPMOVE:
  394.                                         /* Post message to working thread */
  395.     WinPostMsg(hwndThread, WM_DESKTOPMOVE, mp1, mp2);
  396.     break;
  397.  
  398. case WM_SIZE:
  399.                                         /* Request repaint from working thread */
  400.     WinPostMsg(hwndThread, WM_REPAINT, NULL, NULL);
  401. case WM_MOVE:
  402.                                         /* Get the frame area size */
  403.     WinQueryWindowPos(hwndFrame, &HookParameters.swpPC2);
  404.     break;
  405.  
  406. /*                                                                                      *\
  407.  * Syntax: WM_DESKTOPMOVE, NULL, NULL                                                   *
  408. \*                                                                                      */
  409. case WM_MOUSEMOVE:                      /* Set mouse pointer accordingly to last smarticon pressed */
  410.     if(usMenuCommand==ID_ICONMOVE) WinSetPointer(HWND_DESKTOP, hPointerMove);
  411.     else WinSetPointer(HWND_DESKTOP, hPointerAction);
  412.     break;
  413.  
  414. /*                                                                                      *\
  415.  * Syntax: WM_HOTKEY, (USHORT usFlags, USHORT usCh), ULONG ulKeyDataIndex               *
  416. \*                                                                                      */
  417. case WM_HOTKEY:
  418.                                         /* Just pass this message to the working thread */
  419.     WinPostMsg(hwndThread, WM_HOTKEY, MPFROMLONG(mp1), MPFROMLONG(mp2));
  420.     break;
  421.  
  422. case WM_BUTTON1DOWN:
  423.     return((MRESULT)TRUE);              /* Avoid default window procedure which sets the
  424.                                            focus to PC/2 */
  425.     break;
  426.  
  427. /*                                                                                      *\
  428.  * Syntax: WM_BUTTON2DOWN, (LONG lClickX), (LONG lClickY)                               *
  429. \*                                                                                      */
  430. case WM_BUTTON2DOWN:
  431. /*                                                                                      *\
  432.  * This message detected and passed from the PC/2 window procedure is used to track or  *
  433.  * perform certain actions on windows on the Virtual Desktops.                          *
  434. \*                                                                                      */
  435.     {
  436.     LONG        lClickX, lClickY;       /* Pointer position during click */
  437.     ULONG       ulWindowIndex;          /* Index in Windows.wdWindow[] */
  438.     BOOL        bFound=FALSE;           /* TRUE if one window was found */
  439.     TRACKINFO   tiWindow;               /* Trackinfo structure for one window */
  440.  
  441.                                         /* Get position of mouse button 1 down */
  442.     lClickX=(ULONG)(SHORT1FROMMP(mp1));
  443.     lClickY=(ULONG)(SHORT2FROMMP(mp1));
  444.     lClickX=((float)(lClickX-HookParameters.ptlOrigin.x))/HookParameters.fScaleX;
  445.     lClickY=((float)(lClickY-HookParameters.ptlOrigin.y))/HookParameters.fScaleY;
  446.                                         /* Loop for all windows, from topmost to bottommost, on
  447.                                            overview window */
  448.     for(ulWindowIndex=0;
  449.         Windows.ulWindowLast!=(ULONG)-1 && ulWindowIndex<=Windows.ulWindowLast;
  450.         ulWindowIndex++)
  451.         {
  452.                                         /* Ignore invisible windows */
  453.         if(!(Windows.wdWindow[ulWindowIndex].ulStatus & VISIBLE)) continue;
  454.         if((Windows.wdWindow[ulWindowIndex].swpWindow.x<=lClickX) &&
  455.             (Windows.wdWindow[ulWindowIndex].swpWindow.x+Windows.wdWindow[ulWindowIndex].swpWindow.cx>=lClickX) &&
  456.             (Windows.wdWindow[ulWindowIndex].swpWindow.y<=lClickY) &&
  457.             (Windows.wdWindow[ulWindowIndex].swpWindow.y+Windows.wdWindow[ulWindowIndex].swpWindow.cy>=lClickY))
  458.             {                           /* We have found one */
  459.             bFound=TRUE;
  460.             break;
  461.             }
  462.         }
  463.     if(bFound)
  464.         {
  465.         SWP     swpWindow;              /* Copy of Window's position, because working thread may update it */
  466.  
  467.         memcpy(&swpWindow, &Windows.wdWindow[ulWindowIndex].swpWindow, sizeof(SWP));
  468.         switch(usMenuCommand)
  469.         {
  470.         case ID_ICONMOVE:
  471.                                         /* Calculate and draw starting tracking rectangle */
  472.             tiWindow.rclTrack.xLeft=HookParameters.ptlOrigin.x+
  473.                 (float)swpWindow.x*HookParameters.fScaleX;
  474.             tiWindow.rclTrack.yBottom=HookParameters.ptlOrigin.y+
  475.                 (float)swpWindow.y*HookParameters.fScaleY;
  476.             tiWindow.rclTrack.xRight=tiWindow.rclTrack.xLeft+
  477.                 (float)swpWindow.cx*HookParameters.fScaleX;
  478.             tiWindow.rclTrack.yTop=tiWindow.rclTrack.yBottom+
  479.                 (float)swpWindow.cy*HookParameters.fScaleY;
  480.             tiWindow.cxBorder=1;        /* Border width */
  481.             tiWindow.cyBorder=1;
  482.             tiWindow.cxGrid=1;          /* Grid width */
  483.             tiWindow.cyGrid=1;
  484.             tiWindow.cxKeyboard=1;      /* Movement in pixel for keyboard (keyboard currently can't
  485.                                            start tracking) */
  486.             tiWindow.cyKeyboard=1;
  487.                                         /* Minimum tracking size */
  488.             tiWindow.ptlMinTrackSize.x=2;
  489.             tiWindow.ptlMinTrackSize.y=2;
  490.                                         /* Maximum tracking size */
  491.             tiWindow.ptlMaxTrackSize.x=HookParameters.swpPC2Client.cx;
  492.             tiWindow.ptlMaxTrackSize.y=HookParameters.swpPC2Client.cy;
  493.                                         /* Boundary rectangle */
  494.             tiWindow.rclBoundary.xLeft=0;
  495.             tiWindow.rclBoundary.yBottom=0;
  496.             tiWindow.rclBoundary.xRight=HookParameters.swpPC2Client.cx;
  497.             tiWindow.rclBoundary.yTop=HookParameters.swpPC2Client.cy;
  498.                                         /* Tracking options */
  499.             tiWindow.fs=TF_SETPOINTERPOS | TF_MOVE | TF_ALLINBOUNDARY;
  500.             if(WinTrackRect(hwnd, NULLHANDLE, &tiWindow))
  501.                 {                       /* If tracking was successful reposition tracked window */
  502.                 swpWindow.x=((float)(tiWindow.rclTrack.xLeft-HookParameters.ptlOrigin.x))/HookParameters.fScaleX;
  503.                 swpWindow.y=((float)(tiWindow.rclTrack.yBottom-HookParameters.ptlOrigin.y))/HookParameters.fScaleY;
  504.                 WinSetWindowPos(swpWindow.hwnd, HWND_TOP,
  505.                     swpWindow.x, swpWindow.y, 0, 0, SWP_MOVE | SWP_NOADJUST);
  506.                 }
  507.             break;
  508.  
  509.         case ID_ICONZORDERTOP:          /* Set selected window to top of Desktop */
  510.             WinSetWindowPos(swpWindow.hwnd, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER);
  511.             break;
  512.  
  513.         case ID_ICONZORDERBOTTOM:       /* Set selected window to bottom of Desktop */
  514.             WinSetWindowPos(swpWindow.hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_ZORDER);
  515.             break;
  516.  
  517.         case ID_ICONCLOSE:              /* Close selected window by simulating the selection of
  518.                                            the "close" menuitem of the applications's system menu */
  519.             WinPostMsg(swpWindow.hwnd, WM_SYSCOMMAND, MPFROMLONG(SC_CLOSE), MPFROM2SHORT(CMDSRC_MENU, FALSE));
  520.             break;
  521.  
  522.         case ID_ICONMAXIMIZE:           /* Maximize selected window */
  523.             WinSetWindowPos(swpWindow.hwnd, HWND_TOP, 0, 0, 0, 0, SWP_MAXIMIZE);
  524.             break;
  525.  
  526.         case ID_ICONMINIMIZE:           /* Maximize selected window */
  527.             WinSetWindowPos(swpWindow.hwnd, HWND_TOP, 0, 0, 0, 0, SWP_MINIMIZE);
  528.             break;
  529.  
  530.         case ID_ICONRESTORE:            /* Maximize selected window */
  531.             WinSetWindowPos(swpWindow.hwnd, HWND_TOP, 0, 0, 0, 0, SWP_RESTORE);
  532.             break;
  533.         }
  534.         }
  535.     }
  536.     break;
  537.  
  538. case WM_BUTTON1DBLCLK:
  539.                                         /* Just pass this message to the working thread */
  540.     WinPostMsg(hwndThread, WM_BUTTON1DBLCLK, MPFROMLONG(mp1), MPFROMLONG(mp2));
  541.     break;
  542.  
  543. /*                                                                                      *\
  544.  * Syntax: WM_WINDOWLIST, (USHORT x, USHORT y), NULL                                    *
  545. \*                                                                                      */
  546. case WM_WINDOWLIST:
  547.                                         /* Pass this message to the working thread */
  548.     WinPostMsg(hwndThread, WM_WINDOWLIST, MPFROMLONG(mp1), MPFROMLONG(mp2));
  549.     break;
  550.  
  551. /*                                                                                      *\
  552.  * Syntax: WM_POPUPMENU, (SHORT x, SHORT y), HWND hwndPopup                             *
  553. \*                                                                                      */
  554. case WM_POPUPMENU:
  555. /*                                                                                      *\
  556.  * The hook found that button 1 was clicked on the Desktop and sent us this message. It *
  557.  * is either a WM_BUTTON1CLICK or WM_BUTTON1DBLCLK. First we obtain the focus, to be    *
  558.  * able to start our programs in the foreground.                                        *
  559. \*                                                                                      */
  560.     {
  561.     POINTL      ptlPopupPosition;
  562.     HWND        hwndPopup;
  563.     USHORT      fsOptions=PU_NONE | PU_KEYBOARD | PU_MOUSEBUTTON1 |
  564.                           PU_HCONSTRAIN | PU_VCONSTRAIN;
  565.  
  566.     if(bConfigDialog==FALSE)            /* Display Configuration dialog if the Popup-Menu
  567.                                            doesn't contain one */
  568.                                         /* Post message to load Configure PC/2 dialog box.
  569.                                            We post it because send is synchronous and will
  570.                                            block the message queue which however must
  571.                                            not be blocked in order to handle the
  572.                                            Configuration dialog window procedure */
  573.         WinPostMsg(hwnd, WM_COMMAND, MPFROMSHORT(ID_CONFIGDIALOG), MPFROMSHORT(CMDSRC_OTHER));
  574.     else
  575.         {                               /* If there is one menuentry in the Popup-Menu
  576.                                            position on the first */
  577.         if(pPopupMenu->Item!=ENTRYEMPTY) fsOptions|=PU_POSITIONONITEM;
  578.                                         /* Get the position and window, where the user
  579.                                            clicked to get the Popup-Menu */
  580.         ptlPopupPosition.x=(ULONG)SHORT1FROMMP(mp1);
  581.         ptlPopupPosition.y=(ULONG)SHORT2FROMMP(mp1);
  582.         hwndPopup=HWNDFROMMP(mp2);
  583.                                         /* Map these window coordinated to display
  584.                                            coordinates, so that the Menu will be
  585.                                            displayed relative to the lower, left edge
  586.                                            of the display */
  587.         WinMapWindowPoints(hwndPopup, HWND_DESKTOP, &ptlPopupPosition,
  588.             sizeof(ptlPopupPosition)/sizeof(POINTL));
  589.                                         /* Set focus to our window */
  590.         WinSetFocus(HWND_DESKTOP, hwnd);
  591.         if(!WinPopupMenu(               /* Pop up the popup menu */
  592.             HWND_DESKTOP,               /* Parent window handle */
  593.             hwnd,                       /* Owner window handle that receives all the
  594.                                            notification messages generated by the pop-up
  595.                                            menu */
  596.             hwndPopupMenu,              /* Popup menu window handle */
  597.             ptlPopupPosition.x,         /* x-coordinate of mouse pointer for popup menu */
  598.             ptlPopupPosition.y,         /* y-coordinate of mouse pointer for popup menu */
  599.             pPopupMenu->id,             /* Input item identity, if PU_POSITIONONITEM or
  600.                                            PU_SELECTITEM is set */
  601.             fsOptions)                  /* Input options */
  602.         ) GEN_ERR(hab, (HWND)NULL, (HWND)NULL);
  603.         }
  604.     break;
  605.     }
  606.  
  607. /*                                                                                      *\
  608.  * Syntax: WM_MOVEREQUEST, (USHORT usMouseXPos, USHORT usMouseYPos), (ULONG ulMoveFlag) *
  609. \*                                                                                      */
  610. case WM_MOVEREQUEST:
  611.     WinPostMsg(hwndThread, WM_MOVEREQUEST, MPFROMLONG(mp1), MPFROMLONG(mp2));
  612.     break;
  613.  
  614. case WM_CLOSE:
  615.     if(WinMessageBox(                   /* Ask the user if he really wants to exit */
  616.         HWND_DESKTOP, HWND_DESKTOP,
  617.         "Are you sure you want to close PC/2?",
  618.         "PC/2 - Program Commander/2",
  619.         ID_PC2MAINWINDOW,
  620.         MB_OKCANCEL | MB_ICONQUESTION | MB_DEFBUTTON1)!=MBID_OK)
  621.         return((MRESULT)TRUE);          /* Only exit if OK is pressed */
  622.                                         /* Send WM_QUIT to thread window, because this message
  623.                                            terminates the message loop */
  624.     WinPostMsg(hwndThread, WM_QUIT, NULL, NULL);
  625.                                         /* Write changes to PC2.INI */
  626.     INIAccess(pucFilenameINI, FALSE);
  627.     if(WinReleaseHook(                  /* Release hook */
  628.         hab,                            /* Handle  of anchor block */
  629.         NULLHANDLE,                     /* Release from system hook chain */
  630.         HK_INPUT,                       /* Hook of system input queue */
  631.         (PFN)PC2DLL_Hook,               /* Pointer to hook procedure */
  632.         hDllPc2)==FALSE)
  633.         {
  634.         USR_ERR("Unhooking the system input queue failed, System ShutDown suggested - exiting...",
  635.             hwndFrame, hwndClient);
  636.         WinPostMsg(hwnd, WM_QUIT, NULL, NULL);
  637.         }
  638.     DosFreeModule(hDllPc2);             /* Free DLL reference */
  639.                                         /* Post exit message */
  640.     WinPostMsg(hwnd, WM_QUIT, NULL, NULL);
  641.     break;
  642.  
  643. case HM_ERROR:
  644.    {
  645.    GEN_ERR(hab, hwndFrame, hwndClient);
  646.    break;
  647.    }
  648.  
  649. case WM_COMMAND:
  650.     {
  651.     USHORT      command;
  652.  
  653.     command=SHORT1FROMMP(mp1);          /* Extract the command value */
  654. /*                                                                                      *\
  655.  * Filter the IDs of the user defined items of the Popup-Menu. If one is found, call    *
  656.  * SearchItem() to search for the corresponding MENUDATA structure, copy it to a        *
  657.  * SESSIONDATA structure and start the session.                                         *
  658. \*                                                                                      */
  659.     if((command>=USERITEMFIRST) && (command<=USERITEMLAST))
  660.         {
  661.         ULONG           id=(ULONG)command;
  662.         MENUDATA        *pMD=NULL;
  663.  
  664.                                         /* Search in the linked list for this entry */
  665.         if((pMD=SearchItem(pPopupMenu, &id))!=NULL)
  666.             if(pMD->Item==ENTRYMENUITEM)
  667.                 {  
  668.                                         /* Load SessionData with MENUDATA structure */
  669.                 LoadMenuData2SessionData(pMD, &SessionData);
  670.                                         /* If user defined size and position defined
  671.                                            set SWP_MOVEWINDOW flag, which invokes a
  672.                                            reposition of the window, the first time the
  673.                                            started application's window is found. The flag
  674.                                            will be reset afterwards */
  675.                 if(pMD->PgmControl & SSF_CONTROL_SETPOS)
  676.                     {                   /* If have to move the window create it invisible
  677.                                            first to avoid drawing of window before movement.
  678.                                            If the window should be not invisible set flag
  679.                                            SWP_MOVEWINDOWVISIBLE to show window after movement.
  680.                                            The flag will be reset afterwards. */
  681.                     if(pMD->PgmControl & SSF_CONTROL_INVISIBLE)
  682.                         pMD->SwpFlag|=SWP_MOVEWINDOW;
  683.                     else
  684.                         pMD->SwpFlag|=(SWP_MOVEWINDOW | SWP_MOVEWINDOWVISIBLE);
  685.                                         /* Create window invisible before movement */
  686.                     SessionData.PgmControl|=SSF_CONTROL_INVISIBLE;
  687.                     }
  688.                                         /* Start the session */
  689.                 StartSession(&SessionData);
  690.                 }
  691.         break;                          /* We don't need further testing for this command */
  692.         }
  693.     hwndMenu=WinWindowFromID(hwndFrame, FID_MENU);
  694.     switch(command)
  695.     {
  696.                                         /* Test for messages sent from smarticons */
  697.     case ID_ICONEXIT:
  698.         if(usMenuCommand!=ID_ICONMOVE)
  699.             {
  700.             WinSendMsg(hwndMenu, MM_SETITEMATTR,
  701.                 MPFROM2SHORT(usMenuCommand, TRUE), MPFROM2SHORT(MIA_FRAMED|MIA_HILITED, 0));
  702.             WinSendMsg(hwndMenu, MM_SETITEMATTR,
  703.                 MPFROM2SHORT(ID_ICONMOVE, TRUE), MPFROM2SHORT(MIA_FRAMED|MIA_HILITED, MIA_FRAMED|MIA_HILITED));
  704.             }
  705.         usMenuCommand=ID_ICONMOVE;
  706.                                         /* Post exit to PC/2 */
  707.         WinPostMsg(hwnd, WM_COMMAND, MPFROMSHORT(ID_EXIT), MPFROMSHORT(CMDSRC_MENU));
  708.         break;
  709.  
  710.     case ID_ICONMOVE:
  711.         if(usMenuCommand!=ID_ICONMOVE)
  712.             {                           /* Remove frame attribute from previous smarticon to move smarticon */
  713.             WinSendMsg(hwndMenu, MM_SETITEMATTR,
  714.                 MPFROM2SHORT(usMenuCommand, TRUE), MPFROM2SHORT(MIA_FRAMED|MIA_HILITED, 0));
  715.             WinSendMsg(hwndMenu, MM_SETITEMATTR,
  716.                 MPFROM2SHORT(ID_ICONMOVE, TRUE), MPFROM2SHORT(MIA_FRAMED|MIA_HILITED, MIA_FRAMED|MIA_HILITED));
  717.             }
  718.         usMenuCommand=ID_ICONMOVE;
  719.         break;
  720.  
  721.     case ID_ICONZORDERTOP:
  722.         if(usMenuCommand!=ID_ICONZORDERTOP)
  723.             {
  724.             WinSendMsg(hwndMenu, MM_SETITEMATTR,
  725.                 MPFROM2SHORT(usMenuCommand, TRUE), MPFROM2SHORT(MIA_FRAMED|MIA_HILITED, 0));
  726.             WinSendMsg(hwndMenu, MM_SETITEMATTR,
  727.                 MPFROM2SHORT(ID_ICONZORDERTOP, TRUE), MPFROM2SHORT(MIA_FRAMED|MIA_HILITED, MIA_FRAMED|MIA_HILITED));
  728.             }
  729.         usMenuCommand=ID_ICONZORDERTOP;
  730.         break;
  731.  
  732.     case ID_ICONZORDERBOTTOM:
  733.         if(usMenuCommand!=ID_ICONZORDERBOTTOM)
  734.             {
  735.             WinSendMsg(hwndMenu, MM_SETITEMATTR,
  736.                 MPFROM2SHORT(usMenuCommand, TRUE), MPFROM2SHORT(MIA_FRAMED|MIA_HILITED, 0));
  737.             WinSendMsg(hwndMenu, MM_SETITEMATTR,
  738.                 MPFROM2SHORT(ID_ICONZORDERBOTTOM, TRUE), MPFROM2SHORT(MIA_FRAMED|MIA_HILITED, MIA_FRAMED|MIA_HILITED));
  739.             }
  740.         usMenuCommand=ID_ICONZORDERBOTTOM;
  741.         break;
  742.  
  743.     case ID_ICONCLOSE:
  744.         if(usMenuCommand!=ID_ICONCLOSE)
  745.             {
  746.             WinSendMsg(hwndMenu, MM_SETITEMATTR,
  747.                 MPFROM2SHORT(usMenuCommand, TRUE), MPFROM2SHORT(MIA_FRAMED|MIA_HILITED, 0));
  748.             WinSendMsg(hwndMenu, MM_SETITEMATTR,
  749.                 MPFROM2SHORT(ID_ICONCLOSE, TRUE), MPFROM2SHORT(MIA_FRAMED|MIA_HILITED, MIA_FRAMED|MIA_HILITED));
  750.             }
  751.         usMenuCommand=ID_ICONCLOSE;
  752.         break;
  753.  
  754.     case ID_ICONMAXIMIZE:
  755.         if(usMenuCommand!=ID_ICONMAXIMIZE)
  756.             {
  757.             WinSendMsg(hwndMenu, MM_SETITEMATTR,
  758.                 MPFROM2SHORT(usMenuCommand, TRUE), MPFROM2SHORT(MIA_FRAMED|MIA_HILITED, 0));
  759.             WinSendMsg(hwndMenu, MM_SETITEMATTR,
  760.                 MPFROM2SHORT(ID_ICONMAXIMIZE, TRUE), MPFROM2SHORT(MIA_FRAMED|MIA_HILITED, MIA_FRAMED|MIA_HILITED));
  761.             }
  762.         usMenuCommand=ID_ICONMAXIMIZE;
  763.         break;
  764.  
  765.     case ID_ICONMINIMIZE:
  766.         if(usMenuCommand!=ID_ICONMINIMIZE)
  767.             {
  768.             WinSendMsg(hwndMenu, MM_SETITEMATTR,
  769.                 MPFROM2SHORT(usMenuCommand, TRUE), MPFROM2SHORT(MIA_FRAMED|MIA_HILITED, 0));
  770.             WinSendMsg(hwndMenu, MM_SETITEMATTR,
  771.                 MPFROM2SHORT(ID_ICONMINIMIZE, TRUE), MPFROM2SHORT(MIA_FRAMED|MIA_HILITED, MIA_FRAMED|MIA_HILITED));
  772.             }
  773.         usMenuCommand=ID_ICONMINIMIZE;
  774.         break;
  775.  
  776.     case ID_ICONRESTORE:
  777.         if(usMenuCommand!=ID_ICONRESTORE)
  778.             {
  779.             WinSendMsg(hwndMenu, MM_SETITEMATTR,
  780.                 MPFROM2SHORT(usMenuCommand, TRUE), MPFROM2SHORT(MIA_FRAMED|MIA_HILITED, 0));
  781.             WinSendMsg(hwndMenu, MM_SETITEMATTR,
  782.                 MPFROM2SHORT(ID_ICONRESTORE, TRUE), MPFROM2SHORT(MIA_FRAMED|MIA_HILITED, MIA_FRAMED|MIA_HILITED));
  783.             }
  784.         usMenuCommand=ID_ICONRESTORE;
  785.         break;
  786.  
  787.     case ID_ICONSHUTDOWN:
  788.         if(usMenuCommand!=ID_ICONMOVE)
  789.             {
  790.             WinSendMsg(hwndMenu, MM_SETITEMATTR,
  791.                 MPFROM2SHORT(usMenuCommand, TRUE), MPFROM2SHORT(MIA_FRAMED|MIA_HILITED, 0));
  792.             WinSendMsg(hwndMenu, MM_SETITEMATTR,
  793.                 MPFROM2SHORT(ID_ICONMOVE, TRUE), MPFROM2SHORT(MIA_FRAMED|MIA_HILITED, MIA_FRAMED|MIA_HILITED));
  794.             }
  795.         usMenuCommand=ID_ICONMOVE;
  796.                                         /* Post ShutDowm OS/2 to PC/2 */
  797.         WinPostMsg(hwnd, WM_COMMAND, MPFROMSHORT(ID_SHUTDOWN), MPFROMSHORT(CMDSRC_MENU));
  798.         break;
  799.  
  800.     case ID_ICONHELP:
  801.         if(usMenuCommand!=ID_ICONMOVE)
  802.             {
  803.             WinSendMsg(hwndMenu, MM_SETITEMATTR,
  804.                 MPFROM2SHORT(usMenuCommand, TRUE), MPFROM2SHORT(MIA_FRAMED|MIA_HILITED, 0));
  805.             WinSendMsg(hwndMenu, MM_SETITEMATTR,
  806.                 MPFROM2SHORT(ID_ICONMOVE, TRUE), MPFROM2SHORT(MIA_FRAMED|MIA_HILITED, MIA_FRAMED|MIA_HILITED));
  807.             }
  808.         usMenuCommand=ID_ICONMOVE;
  809.                                         /* Post help to PC/2 */
  810.         WinPostMsg(hwnd, WM_COMMAND, MPFROMSHORT(ID_HELP), MPFROMSHORT(CMDSRC_MENU));
  811.         break;
  812.  
  813.     case ID_HELP:                       /* Display general help panel */
  814.         if(hwndHelp!=NULLHANDLE) WinSendMsg(
  815.             hwndHelp,                   /* Help window */
  816.             HM_DISPLAY_HELP,            /* Display a help panel */
  817.             MPFROMSHORT(ID_HELP),       /* Panel ID in ressource file */
  818.             HM_RESOURCEID);             /* MP1 points to the help window identity */
  819.         break;
  820.  
  821.     case ID_CONFIGDIALOG:               /* Popup menuitem Configure Menu selected */
  822.         if(!WinDlgBox(                  /* Start Configure PC/2 dialog box */
  823.             HWND_DESKTOP,               /* DESKTOP is parent */
  824.             HWND_DESKTOP,               /* DESKTOP is owner */
  825.             CD_DialogProcedure,         /* Dialog procedure of Program Installation
  826.                                            dialog */
  827.             0,                          /* Ressource is .EXE file */
  828.             CDID_CONFIGDIALOG,          /* ID of Configure PC/2 dialog */
  829.             0))                         /* No initialization data */
  830.         GEN_ERR(hab, hwndFrame, hwndClient);
  831.         break;
  832.  
  833.     case ID_DESKTOPDIALOG:              /* Popup menuitem Configure Desktop selected */
  834.         if(!WinDlgBox(HWND_DESKTOP, HWND_DESKTOP, DD_DialogProcedure,
  835.             0, DDID_DESKTOPDIALOG, 0))
  836.         GEN_ERR(hab, hwndFrame, hwndClient);
  837.         break;
  838.  
  839.     case ID_SHUTDOWN:                   /* ShutDown OS/2 menuitem selected */
  840.         if(WinMessageBox(               /* Ask the user if he really wants to shut down OS/2 */
  841.         HWND_DESKTOP, HWND_DESKTOP,
  842.         "Are you really sure you want to ShutDown OS/2?",
  843.         "PC/2 - Program Commander/2",
  844.         ID_PC2MAINWINDOW,
  845.         MB_OKCANCEL | MB_ICONQUESTION | MB_DEFBUTTON1)!=MBID_OK)
  846.         return((MRESULT)TRUE);          /* Only shut down if OK is pressed */
  847.         if(!WinDlgBox(                  /* Start ShutDown OS/2 dialog box */
  848.             HWND_DESKTOP, HWND_DESKTOP, SD_DialogProcedure, 0,
  849.             SDID_SHUTDOWNDIALOG, 0))
  850.         GEN_ERR(hab, hwndFrame, hwndClient);
  851.         break;
  852.  
  853.     case ID_EXIT:                       /* User selected F3 to shutdown PC/2 */
  854.         WinPostMsg(hwnd, WM_CLOSE, 0, 0);
  855.         break;
  856.  
  857.     case ID_ABOUTDIALOG:                /* User selected About PC/2 dialog */
  858.         if(!WinDlgBox(                  /* Start About PC/2 dialog box */
  859.             HWND_DESKTOP,               /* DESKTOP is parent */
  860.             HWND_DESKTOP,               /* DESKTOP is owner */
  861.             AD_DialogProcedure,         /* Dialog procedure of Program Installation
  862.                                            dialog */
  863.             0,                          /* Ressource is .EXE file */
  864.             ADID_ABOUTDIALOG,           /* ID of Program Installation dialog */
  865.             0))                         /* No initialization data */
  866.             GEN_ERR(hab, hwndFrame, hwndClient);
  867.         break;
  868.     }
  869.     break;
  870.     }
  871.  
  872. default:                                /* Default window procedure must be called */
  873.     return((MRESULT)WinDefWindowProc(hwnd, msg, mp1, mp2));
  874. }
  875. return((MRESULT)FALSE);                 /* We have handled the message */
  876. }
  877.  
  878. /*--------------------------------------------------------------------------------------*\
  879.  * This dialog procedure handles the PC/2 - Configuration (Setup) dialog.               *
  880.  * Req: none                                                                            *
  881. \*--------------------------------------------------------------------------------------*/
  882. MRESULT  EXPENTRY CD_DialogProcedure(HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2)
  883. {
  884. switch(msg)
  885. {
  886. case WM_INITDLG:
  887.     {
  888.     SWP         swp;
  889.  
  890.     WinQueryWindowPos(                  /* Query position of dialog window */
  891.         hwndDlg,                        /* Handle of dialog window */
  892.         &swp);                          /* Fill with position */
  893.     WinSetWindowPos(                    /* Set dialog window position */
  894.         hwndDlg,                        /* Handle of dialog window */
  895.         HWND_TOP,                       /* Position on top and center of DESKTOP */
  896.         (swpScreen.cx-swp.cx)/2,
  897.         (swpScreen.cy-swp.cy)/2,
  898.         0,
  899.         0,
  900.         SWP_MOVE);
  901.                                         /* Initialize the listbox */
  902.     WinSendMsg(hwndDlg, WM_LOADPOPUPMENU, MPFROMP(pMenuData), NULL);
  903.     break;
  904.     }
  905.  
  906. /*                                                                                      *\
  907.  * Syntax: WM_LOADPOPUPMENU, *MENUDATA, NULL                                            *
  908. \*                                                                                      */
  909. case WM_LOADPOPUPMENU:                  /* Load the current level of the Popup-Menu in
  910.                                            the listbox after removing the old items */
  911.     {
  912.     MENUDATA    *pMD;
  913.  
  914.     pMD=PVOIDFROMMP(mp1);               /* Get the pointer to the first MENUDATA of the
  915.                                            current level */
  916.     WinSendDlgItemMsg(                  /* Send message to listbox */
  917.         hwndDlg,                        /* Handle of dialog window */
  918.         CDLB_MENUPROGRAM,               /* Submenu & Program listbox */
  919.         LM_DELETEALL,                   /* Delete all list box items */
  920.         (MPARAM)NULL,
  921.         (MPARAM)NULL);
  922.     if(pMD==NULL) break;                /* If linked list is empty break out */
  923.     do
  924.     {
  925.         if(pMD->Item==ENTRYSUBMENU)     /* It is a Submenu */
  926.             {
  927.             UCHAR       Buffer[MAXNAMEL+4];
  928.                                         /* Add >> for a Submenu */
  929.             sprintf(Buffer, "%s >>", pMD->PgmTitle);
  930.             WinSendDlgItemMsg(
  931.                 hwndDlg,
  932.                 CDLB_MENUPROGRAM,
  933.                 LM_INSERTITEM,          /* Insert Submenu Title at the end */
  934.                 MPFROMSHORT(LIT_END),
  935.                 MPFROMP(Buffer));
  936.             }
  937.         if(pMD->Item==ENTRYMENUITEM)    /* It's a Menuitem */
  938.             WinSendDlgItemMsg(
  939.                 hwndDlg,
  940.                 CDLB_MENUPROGRAM,
  941.                 LM_INSERTITEM,          /* Insert Menuitem Title at the end */
  942.                 MPFROMSHORT(LIT_END),
  943.                 MPFROMP(pMD->PgmTitle));
  944.         if(pMD->Item==ENTRYCONTROL)     /* It's a Control */
  945.             {
  946.             WinSendDlgItemMsg(
  947.                 hwndDlg,
  948.                 CDLB_MENUPROGRAM,
  949.                 LM_INSERTITEM,          /* Insert Control Title at the end */
  950.                 MPFROMSHORT(LIT_END),
  951.                 MPFROMP(pMD->PgmTitle));
  952.             }
  953.                                         /* It may also be an empty entry, but then we
  954.                                            ignore it, because it must be filled with
  955.                                            Menuitem or Submenu data first */
  956.         if(pMD->Next!=NULL)             /* Get through linked list without diving into
  957.                                            Submenus */
  958.                 pMD=pMD->Next;
  959.         else break;                     /* We're at the end of the linked list */
  960.     }while(TRUE);
  961.     break;
  962.     }
  963.  
  964. /*                                                                                      *\
  965.  * Syntax: WM_SAVEPOPUPMENU, NULL, NULL                                                 *
  966. \*                                                                                      */
  967. case WM_SAVEPOPUPMENU:                  /* Save the Popup-Menu to the configuraion file */
  968.     if((Pc2Profile=fopen(pucFilenameProfile, "w"))==NULL)
  969.         USR_ERR("Cannot open confguration file - changes won't be saved",
  970.                 hwndFrame, hwndClient);
  971.     else
  972.         {
  973.         fprintf(Pc2Profile, "PROFILE START\n");
  974.         SaveMenu(pPopupMenu);           /* Save the menu linked list */
  975.         fprintf(Pc2Profile, "PROFILE END\n");
  976.         fclose(Pc2Profile);
  977.         }
  978.     break;
  979.  
  980. case WM_HELP:                           /* Help pressed */
  981.     WinSendMsg(
  982.         hwndHelp,                       /* Help window */
  983.         HM_DISPLAY_HELP,                /* Display a help panel */
  984.         MPFROMSHORT(ID_CONFIGDIALOG),   /* Panel ID in ressource file */
  985.         HM_RESOURCEID);                 /* MP1 points to the help window identity */
  986.     break;
  987.  
  988. case WM_COMMAND:                        /* Button pressed */
  989.     switch(SHORT1FROMMP(mp1))
  990.     {
  991. /*                                                                                      *\
  992.  * Chain up the linked list until we find the node, where this part-list comes from or  *
  993.  * the beginning of the complete list. The pointer pMenuData is adjusted.               *
  994. \*                                                                                      */
  995.     case CDID_LEVELUP:                  /* Get up one level in the linked list */
  996.         {
  997.         MENUDATA        *pMD;           /* Pointer to a MENUDATA structure to find the
  998.                                            Submenu where this part-list starts */
  999.  
  1000.         pMD=pMenuData;                  /* Point to the first element of the linked list
  1001.                                            at the current level */
  1002.         if(pMD->Back==NULL)             /* If we're at the beginning of the complete linked
  1003.                                            list ignore button */
  1004.             return((MRESULT)FALSE);
  1005.         else pMD=pMD->Back;             /* Submenu which started current level */
  1006.                                         /* Now chain back through the linked list and find
  1007.                                            the element, where the pointer to a Submenu
  1008.                                            equals the back pointer of the first element
  1009.                                            in this Submenu. Then we've found the node */
  1010.         while(TRUE)
  1011.             {
  1012.             if(pMD->Back==NULL)         /* If we're now at the beginning break */
  1013.                 break;
  1014.             if((pMD->Back)->Submenu==pMD)
  1015.                 break;
  1016.             else pMD=pMD->Back;
  1017.             }
  1018.         pMenuData=pMD;                  /* Load as the top element of the current item */
  1019.                                         /* Now redraw items in listbox */
  1020.         WinSendMsg(hwndDlg, WM_LOADPOPUPMENU, MPFROMP(pMenuData), NULL);
  1021.         return((MRESULT)FALSE);         /* We handled this button */
  1022.         }
  1023.  
  1024. /*                                                                                      *\
  1025.  * Test the user selection for being a Submenu. If one found chain into this submenu    *
  1026.  * and adjust the pointer pMenuData.                                                    *
  1027. \*                                                                                      */
  1028.     case CDID_LEVELDOWN:                /* Get down one level in the linked list */
  1029.         {
  1030.         MENUDATA        *pMD;           /* Pointer to a MENUDATA structure to find the
  1031.                                            Submenu to chain into */
  1032.         SHORT           sCount;
  1033.  
  1034.         pMD=pMenuData;                  /* Point to the first element of the linked list
  1035.                                            at the current level */
  1036.                                         /* Send message to listbox */
  1037.         sCount=(SHORT)WinSendDlgItemMsg(
  1038.             hwndDlg,                    /* Handle of dialog window */
  1039.             CDLB_MENUPROGRAM,           /* Submenu & Program listbox */
  1040.             LM_QUERYSELECTION,          /* Query first selected list box item */
  1041.             MPFROMSHORT(LIT_FIRST),
  1042.             (MPARAM)NULL);
  1043.                                         /* If no item selected, ignore this button */
  1044.         if(sCount==LIT_NONE)
  1045.             return((MRESULT)FALSE);
  1046.         for( ;sCount>0; sCount--)       /* Walk through the linked list to the selected
  1047.                                            item */
  1048.             pMD=pMD->Next;
  1049.         if(pMD->Item!=ENTRYSUBMENU)     /* It's not a Submenu that's selected, ignore */
  1050.             return((MRESULT)FALSE);
  1051.         pMenuData=pMD->Submenu;         /* Otherwise chain into this part-list */
  1052.                                         /* Now redraw items in listbox */
  1053.         WinSendMsg(hwndDlg, WM_LOADPOPUPMENU, MPFROMP(pMenuData), NULL);
  1054.         return((MRESULT)FALSE);         /* We handled this button */
  1055.         }
  1056.  
  1057. /*                                                                                      *\
  1058.  * The user selected to add a (Sub)Menu. Thus dismiss the PC/2 Configuration dialog and *
  1059.  * load the (Sub)Menu Installation dialog. The new (Sub)Menu is entered in a            *
  1060.  * STARTSESSION structure named StartSession. Save the changes and reload the PC/2      *
  1061.  * Configuration dialog again.                                                          *
  1062. \*                                                                                      */
  1063.     case CDID_ADDMENU:                  /* Add a Menu to PC/2 Configuration selected */
  1064. /*                                                                                      *\
  1065.  * The user selected to add a Program. Thus dismiss the PC/2 Configuration dialog and   *
  1066.  * load the Menucontrol Addition dialog. The new control style is selected via          *
  1067.  * autoradiobuttons and is fille STARTSESSION structure named StartSession. Save the    *
  1068.  * changes and reload the PC/2 Configuration dialog again.                              *
  1069. \*                                                                                      */
  1070.     case CDID_ADDPROGRAM:               /* Add a Program to PC/2 Configuration selected */
  1071. /*                                                                                      *\
  1072.  * The user selected to add a Control Style. Thus dismiss the PC/2 Configuration dialog *
  1073.  * and load the Program Installation dialog. The new session data is entered in a       *
  1074.  * STARTSESSION structure named StartSession. Save the changes and reload the PC/2      *
  1075.  * Configuration dialog again.                                                          *
  1076. \*                                                                                      */
  1077.     case CDID_ADDCONTROL:               /* Add a Control Entry to PC/2 Configuration selected */
  1078.         {
  1079.         UCHAR           *pU;            /* Temporary character pointer */
  1080.         MENUDATA        *pMD;           /* Pointer to a MENUDATA structure to insert a
  1081.                                            new MENUDATA stucture after */
  1082.         MENUDATA        *pMDNew;        /* Temporary pointer for the new item to be inserted
  1083.                                            after pMD */
  1084.         SHORT           sCount;
  1085.  
  1086.         pMD=pMenuData;                  /* Point to the first element of the linked list
  1087.                                            at the current level */
  1088.                                         /* Send message to listbox */
  1089.         sCount=(SHORT)WinSendDlgItemMsg(
  1090.             hwndDlg,                    /* Handle of dialog window */
  1091.             CDLB_MENUPROGRAM,           /* Submenu & Program listbox */
  1092.             LM_QUERYSELECTION,          /* Query first selected list box item */
  1093.             MPFROMSHORT(LIT_FIRST),
  1094.             (MPARAM)NULL);
  1095.                                         /* If no item selected, and there exists one,
  1096.                                            add the new Menuitem after the last available
  1097.                                            Menuitem by querying the number from the listbox.
  1098.                                            Subtract 0 because we use 0-based instead 1-based. */
  1099.         if((sCount==LIT_NONE) && (pMenuData->Item!=ENTRYEMPTY))
  1100.             sCount=(SHORT)WinSendDlgItemMsg(hwndDlg, CDLB_MENUPROGRAM, LM_QUERYITEMCOUNT,
  1101.                 MPFROM2SHORT(NULL, NULL), (MPARAM)NULL)-1;
  1102.  
  1103.         for( ;sCount>0; sCount--)       /* Walk through the linked list to the selected
  1104.                                            item */
  1105.             pMD=pMD->Next;
  1106.                                         /* Allocate a new item */
  1107.         pMDNew=AllocateMenuData();
  1108.         if(SHORT1FROMMP(mp1)!=CDID_ADDCONTROL)
  1109.             {                           /* Don't modify MenuData structure if a control entry
  1110.                                            is added */
  1111.             strcpy(pU=malloc(strlen("Insert here please")+1), "Insert here please");
  1112.             free(pMDNew->PgmTitle);
  1113.             pMDNew->PgmTitle=pU;
  1114.             pMDNew->id=MenuDataId++;    /* Increment ID only for non control entries, because
  1115.                                            control entries get their own unique ID */
  1116.             }
  1117.         LoadMenuData2SessionData(pMDNew, &SessionData);
  1118.         WinDismissDlg(hwndDlg, TRUE);   /* Clear up Configuration dialog */
  1119.         if(SHORT1FROMMP(mp1)==CDID_ADDMENU)
  1120.             {
  1121.             if(!WinDlgBox(              /* Start Addmenu PC/2 dialog box */
  1122.                 HWND_DESKTOP,           /* DESKTOP is parent */
  1123.                 HWND_DESKTOP,           /* DESKTOP is owner */
  1124.                 MI_DialogProcedure,     /* Dialog procedure of Program Installation
  1125.                                            dialog */
  1126.                 0,                      /* Ressource is .EXE file */
  1127.                 MIID_MENUDIALOG,        /* ID of Addmenu PC/2 dialog */
  1128.                 0))                     /* No initialization data */
  1129.                 GEN_ERR(hab, hwndFrame, hwndClient);
  1130.             }
  1131.         if(SHORT1FROMMP(mp1)==CDID_ADDPROGRAM)
  1132.             {
  1133.             if(!WinDlgBox(              /* Start Program Installation dialog box */
  1134.                 HWND_DESKTOP,           /* DESKTOP is parent */
  1135.                 HWND_DESKTOP,           /* DESKTOP is owner */
  1136.                 PI_DialogProcedure,     /* Dialog procedure of Program Installation
  1137.                                            dialog */
  1138.                 0,                      /* Ressource is .EXE file */
  1139.                 PIID_PROGRAMDIALOG,     /* ID of Addprogram PC/2 dialog */
  1140.                 0))                     /* No initialization data */
  1141.                 GEN_ERR(hab, hwndFrame, hwndClient);
  1142.             }
  1143.         if(SHORT1FROMMP(mp1)==CDID_ADDCONTROL)
  1144.             {
  1145.             if(!WinDlgBox(              /* Start Menucontrol Addition dialog box */
  1146.                 HWND_DESKTOP,           /* DESKTOP is parent */
  1147.                 HWND_DESKTOP,           /* DESKTOP is owner */
  1148.                 MD_DialogProcedure,     /* Dialog procedure of Menucontrol Addition
  1149.                                            dialog */
  1150.                 0,                      /* Ressource is .EXE file */
  1151.                 MDID_CONTROLDIALOG,     /* ID of Addmenucontrol PC/2 dialog */
  1152.                 0))                     /* No initialization data */
  1153.                 GEN_ERR(hab, hwndFrame, hwndClient);
  1154.             }
  1155.         if(DialogResult==DID_OK)        /* If manipulation is done successfully, then load
  1156.                                            the SESSIONDATA structure back to the MENUDATA
  1157.                                            structure and save the changes */
  1158.             {
  1159.             LoadSessionData2MenuData(pMDNew, &SessionData);
  1160.             if(pMD->Item!=ENTRYEMPTY)   /* Add new entry, if the current entry isn't empty */
  1161.                 {
  1162.                 if(SHORT1FROMMP(mp1)==CDID_ADDMENU)
  1163.                     {                   /* It it is a Submenu, we also must add an empty
  1164.                                            first item for it */
  1165.                     MENUDATA    *pMDTemp;
  1166.  
  1167.                     pMDTemp=AllocateMenuData();
  1168.                     pMDNew->Submenu=pMDTemp;
  1169.                     pMDTemp->Back=pMDNew;
  1170.                     pMDNew->Item=ENTRYSUBMENU;
  1171.                     }
  1172.                 if(SHORT1FROMMP(mp1)==CDID_ADDPROGRAM) pMDNew->Item=ENTRYMENUITEM;
  1173.                 if(SHORT1FROMMP(mp1)==CDID_ADDCONTROL)
  1174.                     {                   /* For controls also add the ID of the control. These
  1175.                                            controls have an predefined ID because the action
  1176.                                            they should start is allways the same */
  1177.                     pMDNew->Item=ENTRYCONTROL;
  1178.                     if(!strcmp(pMDNew->PgmTitle, CTRL_CONFIGMENU))
  1179.                         {               /* If the Configuration Dialog is found set flag
  1180.                                            to true */
  1181.                         bConfigDialog=TRUE;
  1182.                         pMDNew->id=ID_CONFIGDIALOG;
  1183.                         }
  1184.                     if(!strcmp(pMDNew->PgmTitle, CTRL_CONFIGDESKTOP)) pMDNew->id=ID_DESKTOPDIALOG;
  1185.                     if(!strcmp(pMDNew->PgmTitle, CTRL_ABOUT)) pMDNew->id=ID_ABOUTDIALOG;
  1186.                     if(!strcmp(pMDNew->PgmTitle, CTRL_SHUTDOWN)) pMDNew->id=ID_SHUTDOWN;
  1187.                     if(!strcmp(pMDNew->PgmTitle, CTRL_HELP)) pMDNew->id=ID_HELP;
  1188.                     if(!strcmp(pMDNew->PgmTitle, CTRL_EXIT)) pMDNew->id=ID_EXIT;
  1189.                                         /* We assume that more than 1 separator may occur
  1190.                                            so to be able add, modify or delete on menuitems
  1191.                                            define a unique one */
  1192.                     if(!strcmp(pMDNew->PgmTitle, CTRL_BREAKSEPARATOR)) pMDNew->id=MenuDataId++;;
  1193.                     if(!strcmp(pMDNew->PgmTitle, CTRL_SEPARATOR)) pMDNew->id=MenuDataId++;;
  1194.                     }
  1195.                 if(pMD->Next!=NULL) (pMD->Next)->Back=pMDNew;
  1196.                 pMDNew->Next=pMD->Next;
  1197.                 pMDNew->Back=pMD;
  1198.                 pMD->Next=pMDNew;
  1199.                                         /* Insert item after the existing item */
  1200.                 SetPopupMenu(MM_INSERTITEMMENUITEM, MPFROMP(pMDNew), MPFROMLONG(pMD->id));
  1201.                 }
  1202.             else                        /* If it is an empty entry fill it with user data */
  1203.                 {
  1204.                 UCHAR   *pU;            /* Temporary character pointer */
  1205.  
  1206.                 pMD->id=pMDNew->id;
  1207.                 if(SHORT1FROMMP(mp1)==CDID_ADDMENU)
  1208.                     {                   /* It it is a Submenu, we also must add an empty
  1209.                                            first item for it */
  1210.                     MENUDATA    *pMDTemp;
  1211.  
  1212.                     pMDTemp=AllocateMenuData();
  1213.                     pMD->Submenu=pMDTemp;
  1214.                     pMDTemp->Back=pMD;
  1215.                     pMD->Item=ENTRYSUBMENU;
  1216.                     }
  1217.                 if(SHORT1FROMMP(mp1)==CDID_ADDPROGRAM) pMD->Item=ENTRYMENUITEM;
  1218.                 if(SHORT1FROMMP(mp1)==CDID_ADDCONTROL)
  1219.                     {                   /* For controls also add the ID of the control. These
  1220.                                            controls have an predefined ID because the action
  1221.                                            they should start is allways the same */
  1222.                     pMD->Item=ENTRYCONTROL;
  1223.                     if(!strcmp(pMDNew->PgmTitle, CTRL_CONFIGMENU))
  1224.                         {               /* If the Configuration Dialog is found set flag
  1225.                                            to true */
  1226.                         bConfigDialog=TRUE;
  1227.                         pMD->id=ID_CONFIGDIALOG;
  1228.                         }
  1229.                     if(!strcmp(pMDNew->PgmTitle, CTRL_CONFIGDESKTOP)) pMD->id=ID_DESKTOPDIALOG;
  1230.                     if(!strcmp(pMDNew->PgmTitle, CTRL_ABOUT)) pMD->id=ID_ABOUTDIALOG;
  1231.                     if(!strcmp(pMDNew->PgmTitle, CTRL_SHUTDOWN)) pMD->id=ID_SHUTDOWN;
  1232.                     if(!strcmp(pMDNew->PgmTitle, CTRL_HELP)) pMD->id=ID_HELP;
  1233.                     if(!strcmp(pMDNew->PgmTitle, CTRL_EXIT)) pMD->id=ID_EXIT;
  1234.                                         /* We assume that more than 1 separator may occur
  1235.                                            so to be able add, modify or delete on menuitems
  1236.                                            define a unique one */
  1237.                     if(!strcmp(pMDNew->PgmTitle, CTRL_BREAKSEPARATOR)) pMD->id=MenuDataId++;;
  1238.                     if(!strcmp(pMDNew->PgmTitle, CTRL_SEPARATOR)) pMD->id=MenuDataId++;;
  1239.                     }
  1240.                 strcpy(pU=malloc(strlen(pMDNew->PgmTitle)+1), pMDNew->PgmTitle);
  1241.                 free(pMD->PgmTitle);
  1242.                 pMD->PgmTitle=pU;
  1243.                 strcpy(pU=malloc(strlen(pMDNew->WindowTitle)+1), pMDNew->WindowTitle);
  1244.                 free(pMD->WindowTitle);
  1245.                 pMD->WindowTitle=pU;
  1246.                 strcpy(pU=malloc(strlen(pMDNew->PgmName)+1), pMDNew->PgmName);
  1247.                 free(pMD->PgmName);
  1248.                 pMD->PgmName=pU;
  1249.                 strcpy(pU=malloc(strlen(pMDNew->PgmDirectory)+1), pMDNew->PgmDirectory);
  1250.                 free(pMD->PgmDirectory);
  1251.                 pMD->PgmDirectory=pU;
  1252.                 strcpy(pU=malloc(strlen(pMDNew->PgmInputs)+1), pMDNew->PgmInputs);
  1253.                 free(pMD->PgmInputs);
  1254.                 pMD->PgmInputs=pU;
  1255.                 pMD->SessionType=pMDNew->SessionType;
  1256.                 pMD->PgmControl=pMDNew->PgmControl;
  1257.                 pMD->FgBg=pMDNew->FgBg;
  1258.                 pMD->InitXPos=pMDNew->InitXPos;
  1259.                 pMD->InitYPos=pMDNew->InitYPos;
  1260.                 pMD->InitXSize=pMDNew->InitXSize;
  1261.                 pMD->InitYSize=pMDNew->InitYSize;
  1262.                 (pMD->KeyData).usFlags=(pMDNew->KeyData).usFlags;
  1263.                 (pMD->KeyData).usCh=(pMDNew->KeyData).usCh;
  1264.                 pMD->PriorityClass=pMDNew->PriorityClass;
  1265.                 pMD->SwpFlag=pMDNew->SwpFlag;
  1266.                 pMD->PriorityDelta=pMDNew->PriorityDelta;
  1267.                 if(pMD->Back!=NULL)     /* This is the first item of a Submenu, then
  1268.                                            insert it there */
  1269.                     SetPopupMenu(MM_INSERTITEMSUBMENU, MPFROMP(pMD), MPFROMLONG((pMD->Back)->id));
  1270.                 else                    /* This is the complete first item of the linked
  1271.                                            list, so insert at the end */
  1272.                     SetPopupMenu(MM_INSERTITEMMENUITEM, MPFROMP(pMD), MPFROMLONG(MIT_END));
  1273.                 free(pMDNew->PgmTitle); /* Free temporary used structure */
  1274.                 free(pMDNew->WindowTitle);
  1275.                 free(pMDNew->PgmName);
  1276.                 free(pMDNew->PgmDirectory);
  1277.                 free(pMDNew->PgmInputs);
  1278.                 free(pMDNew);
  1279.                 }
  1280.             }
  1281.         else
  1282.             {
  1283.             free(pMDNew->PgmTitle);     /* Free temporary MENUDATA structure */
  1284.             free(pMDNew->WindowTitle);
  1285.             free(pMDNew->PgmName);
  1286.             free(pMDNew->PgmDirectory);
  1287.             free(pMDNew->PgmInputs);
  1288.             free(pMDNew);
  1289.             }
  1290.                                         /* Initialize the listbox */
  1291.         WinSendMsg(hwndDlg, WM_LOADPOPUPMENU, MPFROMP(pMenuData), NULL);
  1292.         if(!WinDlgBox(                  /* Now reload the Configuration dialog */
  1293.             HWND_DESKTOP,
  1294.             HWND_DESKTOP,
  1295.             CD_DialogProcedure,
  1296.             0,
  1297.             CDID_CONFIGDIALOG,
  1298.             0)) GEN_ERR(hab, hwndFrame, hwndClient);
  1299.         break; 
  1300.         }
  1301.  
  1302. /*                                                                                      *\
  1303.  * The user selected to change an item. Thus dismiss the PC/2 Configuration dialog and  *
  1304.  * load the Menu or Program Installation dialog. The new session data is entered in a   *
  1305.  * STARTSESSION structure named StartSession.                                           *
  1306.  * Then reload the PC/2 Configuration dialog again.                                     *
  1307. \*                                                                                      */
  1308.     case CDID_CHANGEENTRY:              /* Change a Menu or Program configuration selected */
  1309.         {
  1310.         MENUDATA        *pMD;
  1311.         SHORT           sCount;
  1312.  
  1313.         pMD=pMenuData;                  /* Point to the first element of the linked list
  1314.                                            at the current level */
  1315.                                         /* Send message to listbox */
  1316.         sCount=(SHORT)WinSendDlgItemMsg(
  1317.             hwndDlg,                    /* Handle of dialog window */
  1318.             CDLB_MENUPROGRAM,           /* Submenu & Program listbox */
  1319.             LM_QUERYSELECTION,          /* Query first selected list box item */
  1320.             MPFROMSHORT(LIT_FIRST),
  1321.             (MPARAM)NULL);
  1322.         if(sCount==LIT_NONE)            /* If no item selected ignore this button */
  1323.             return((MRESULT)FALSE);
  1324.         for( ;sCount>0; sCount--)       /* Walk through the linked list to the selected
  1325.                                            item */
  1326.             pMD=pMD->Next;
  1327.                                         /* Controls can't be changed, they must be
  1328.                                            removed and newly inserted */
  1329.         if(pMD->Item==ENTRYCONTROL) return((MRESULT)FALSE);
  1330.                                         /* Now load the MENUDATA to SESSIONDATA structure
  1331.                                            where the manipulations will take effect */
  1332.         LoadMenuData2SessionData(pMD, &SessionData);
  1333.         WinDismissDlg(hwndDlg, TRUE);   /* Clear up Configuration dialog */
  1334.         if(pMD->Item==ENTRYMENUITEM)
  1335.                                         /* It's a Menuitem  so call the Program
  1336.                                            Installation dialog box */
  1337.             if(!WinDlgBox(              /* Start Program Installation dialog box */
  1338.                 HWND_DESKTOP,           /* DESKTOP is parent */
  1339.                 HWND_DESKTOP,           /* DESKTOP is owner */
  1340.                 PI_DialogProcedure,     /* Dialog procedure of Program Installation
  1341.                                            dialog */
  1342.                 0,                      /* Ressource is .EXE file */
  1343.                 PIID_PROGRAMDIALOG,     /* ID of Program Installation PC/2 dialog */
  1344.                 0))                     /* No initialization data */
  1345.                 GEN_ERR(hab, hwndFrame, hwndClient);
  1346.         if(pMD->Item==ENTRYSUBMENU)
  1347.                                         /* It's a Submenu so call the Menu Installation
  1348.                                            dialog box */
  1349.             if(!WinDlgBox(              /* Start Addmenu PC/2 dialog box */
  1350.                 HWND_DESKTOP,           /* DESKTOP is parent */
  1351.                 HWND_DESKTOP,           /* DESKTOP is owner */
  1352.                 MI_DialogProcedure,     /* Dialog procedure of Program Installation
  1353.                                            dialog */
  1354.                 0,                      /* Ressource is .EXE file */
  1355.                 MIID_MENUDIALOG,        /* ID of Addmenu PC/2 dialog */
  1356.                 0))                     /* No initialization data */
  1357.                 GEN_ERR(hab, hwndFrame, hwndClient);
  1358.         if(DialogResult==DID_OK)        /* If manipulation is done successfully, then load
  1359.                                            the SESSIONDATA structure back to the MENUDATA
  1360.                                            structure and save the changes */
  1361.             {
  1362.             LoadSessionData2MenuData(pMD, &SessionData);
  1363.                                         /* Now change the menuitem text to the new one */
  1364.             SetPopupMenu(MM_SETITEMTEXT, MPFROMP(pMD), MPFROMLONG(pMD->id));
  1365.                                         /* Initialize the listbox */
  1366.             WinSendMsg(hwndDlg, WM_LOADPOPUPMENU, MPFROMP(pMenuData), NULL);
  1367.             }
  1368.         if(!WinDlgBox(                  /* Now reload the Configuration dialog */
  1369.             HWND_DESKTOP,
  1370.             HWND_DESKTOP,
  1371.             CD_DialogProcedure,
  1372.             0,
  1373.             CDID_CONFIGDIALOG,
  1374.             0)) GEN_ERR(hab, hwndFrame, hwndClient);
  1375.         break;
  1376.         }
  1377.  
  1378. /*                                                                                      *\
  1379.  * The user selected to remove an item. If thist item is the only one in the linked     *
  1380.  * list or the first item of a submenu set it to empty otherwise free it's ressources   *
  1381.  * and remove the entry.                                                                *
  1382. \*                                                                                      */
  1383.     case CDID_REMOVEENTRY:              /* Remove a item of the PC/2 Configuration selected */
  1384.         {
  1385.         UCHAR           *pU;
  1386.         MENUDATA        *pMD;
  1387.         SHORT           sCount;
  1388.  
  1389.         pMD=pMenuData;                  /* Point to the first element of the linked list
  1390.                                            at the current level */
  1391.                                         /* Send message to listbox */
  1392.         sCount=(SHORT)WinSendDlgItemMsg(
  1393.             hwndDlg,                    /* Handle of dialog window */
  1394.             CDLB_MENUPROGRAM,           /* Submenu & Program listbox */
  1395.             LM_QUERYSELECTION,          /* Query first selected list box item */
  1396.             MPFROMSHORT(LIT_FIRST),
  1397.             (MPARAM)NULL);
  1398.         if(sCount==LIT_NONE)            /* If no item selected ignore this button */
  1399.             return((MRESULT)FALSE);
  1400.         for( ;sCount>0; sCount--)       /* Walk through the linked list to the selected
  1401.                                            item */
  1402.             pMD=pMD->Next;
  1403.         while(TRUE)
  1404.             {
  1405.             if((pMD->Back==NULL) && (pMD->Next!=NULL))
  1406.                 {                       /* Remove the first item of the complete linked list */
  1407.                 if(pMD->Item==ENTRYSUBMENU)
  1408.                 if((pMD->Submenu)->Item==ENTRYEMPTY)
  1409.                     {                   /* If it is an empty Submenu remove it completely */
  1410.                                         /* Remove the Submenu and the empty first item
  1411.                                            from the Popup-Menu */
  1412.                     SetPopupMenu(MM_DELETEITEM, MPFROMP(pMD), MPFROMLONG(pMD->id));
  1413.                     free((pMD->Submenu)->PgmTitle);
  1414.                     free((pMD->Submenu)->WindowTitle);
  1415.                     free((pMD->Submenu)->PgmName);
  1416.                     free((pMD->Submenu)->PgmDirectory);
  1417.                     free((pMD->Submenu)->PgmInputs);
  1418.                     free(pMD->Submenu);
  1419.                     (pMD->Next)->Back=NULL;
  1420.                                         /* Now next element is the first one */
  1421.                     pPopupMenu=pMD->Next;
  1422.                     pMenuData=pMD->Next;
  1423.                     free(pMD->PgmTitle);
  1424.                     free(pMD->WindowTitle);
  1425.                     free(pMD->PgmName);
  1426.                     free(pMD->PgmDirectory);
  1427.                     free(pMD->PgmInputs);
  1428.                     free(pMD);
  1429.                     break;              /* Ensure we only test once, because each routine
  1430.                                            changes the pointers */
  1431.                     }
  1432.                 if((pMD->Item==ENTRYMENUITEM) || (pMD->Item==ENTRYCONTROL))
  1433.                     {                   /* If it is an empty Menuitem or Control remove it completly */
  1434.                                         /* If the Configuration Dialog is found set flag
  1435.                                            to false */
  1436.                     if(!strcmp(pMD->PgmTitle, CTRL_CONFIGDESKTOP)) bConfigDialog=FALSE;
  1437.                     (pMD->Next)->Back=NULL;
  1438.                                         /* Now next element is the first one */
  1439.                     pPopupMenu=pMD->Next;
  1440.                     pMenuData=pMD->Next;
  1441.                                         /* Remove the item from the Popup-Menu */
  1442.                     SetPopupMenu(MM_DELETEITEM, MPFROMP(pMD), MPFROMLONG(pMD->id));
  1443.                     free(pMD->PgmTitle);
  1444.                     free(pMD->WindowTitle);
  1445.                     free(pMD->PgmName);
  1446.                     free(pMD->PgmDirectory);
  1447.                     free(pMD->PgmInputs);
  1448.                     free(pMD);
  1449.                     break;              /* Ensure we only test once, because each routine
  1450.                                            changes the pointers */
  1451.                     }
  1452.                 }
  1453.             if((pMD->Back==NULL) && (pMD->Next==NULL))
  1454.                 {                       /* If it is the one and only item of the linked list
  1455.                                            set it to empty */
  1456.                 if(pMD->Item==ENTRYSUBMENU)
  1457.                 if((pMD->Submenu)->Item==ENTRYEMPTY)
  1458.                     {                   /* If it is an empty Submenu remove the empty
  1459.                                            item completely */
  1460.                                         /* Remove the item from the Popup-Menu */
  1461.                     SetPopupMenu(MM_DELETEITEM, MPFROMP(pMD), MPFROMLONG(pMD->id));
  1462.                     free((pMD->Submenu)->PgmTitle);
  1463.                     free((pMD->Submenu)->WindowTitle);
  1464.                     free((pMD->Submenu)->PgmName);
  1465.                     free((pMD->Submenu)->PgmDirectory);
  1466.                     free((pMD->Submenu)->PgmInputs);
  1467.                     free(pMD->Submenu);
  1468.                     free(pMD->PgmTitle);
  1469.                     strcpy(pU=malloc(strlen("")+1), "");
  1470.                     pMD->PgmTitle=pU;
  1471.                     free(pMD->WindowTitle);
  1472.                     strcpy(pU=malloc(strlen("")+1), "");
  1473.                     pMD->WindowTitle=pU;
  1474.                     free(pMD->PgmName);
  1475.                     strcpy(pU=malloc(strlen("")+1), "");
  1476.                     pMD->PgmName=pU;
  1477.                     free(pMD->PgmDirectory);
  1478.                     strcpy(pU=malloc(strlen("")+1), "");
  1479.                     pMD->PgmDirectory=pU;
  1480.                     free(pMD->PgmInputs);
  1481.                     strcpy(pU=malloc(strlen("")+1), "");
  1482.                     pMD->PgmInputs=pU;
  1483.                     pMD->Item=ENTRYEMPTY;
  1484.                     pMD->Back=NULL;
  1485.                     pMD->Submenu=NULL;
  1486.                     pMD->Next=NULL;
  1487.                     break;              /* Ensure we only test once, because each routine
  1488.                                            changes the pointers */
  1489.                     }
  1490.                 if((pMD->Item==ENTRYMENUITEM) || (pMD->Item==ENTRYCONTROL))
  1491.                     {                   /* If it is a Menuitem or Control set it to empty */
  1492.                                         /* Remove the item from the Popup-Menu */
  1493.                     SetPopupMenu(MM_DELETEITEM, MPFROMP(pMD), MPFROMLONG(pMD->id));
  1494.                     free(pMD->PgmTitle);
  1495.                     strcpy(pU=malloc(strlen("")+1), "");
  1496.                     pMD->PgmTitle=pU;
  1497.                     free(pMD->WindowTitle);
  1498.                     strcpy(pU=malloc(strlen("")+1), "");
  1499.                     pMD->WindowTitle=pU;
  1500.                     free(pMD->PgmName);
  1501.                     strcpy(pU=malloc(strlen("")+1), "");
  1502.                     pMD->PgmName=pU;
  1503.                     free(pMD->PgmDirectory);
  1504.                     strcpy(pU=malloc(strlen("")+1), "");
  1505.                     pMD->PgmDirectory=pU;
  1506.                     free(pMD->PgmInputs);
  1507.                     strcpy(pU=malloc(strlen("")+1), "");
  1508.                     pMD->PgmInputs=pU;
  1509.                     pMD->Item=ENTRYEMPTY;
  1510.                     pMD->Back=NULL;
  1511.                     pMD->Submenu=NULL;
  1512.                     pMD->Next=NULL;
  1513.                     break;              /* Ensure we only test once, because each routine
  1514.                                            changes the pointers */
  1515.                     }
  1516.                 }
  1517.             if(pMD->Back!=NULL)
  1518.                 {                       /* It is any item of more than one item and not
  1519.                                            the first one */
  1520.                 if(((pMD->Back)->Submenu==pMD) && (pMD->Submenu==NULL) && (pMD->Next==NULL))
  1521.                 {                       /* If it is the first item of a Submenu not followed
  1522.                                            by any item, set it to empty */
  1523.                                         /* Remove the item from the Popup-Menu */
  1524.                     SetPopupMenu(MM_DELETEITEM, MPFROMP(pMD), MPFROMLONG(pMD->id));
  1525.                     free(pMD->PgmTitle);
  1526.                     strcpy(pU=malloc(strlen("")+1), "");
  1527.                     pMD->PgmTitle=pU;
  1528.                     free(pMD->WindowTitle);
  1529.                     strcpy(pU=malloc(strlen("")+1), "");
  1530.                     pMD->WindowTitle=pU;
  1531.                     free(pMD->PgmName);
  1532.                     strcpy(pU=malloc(strlen("")+1), "");
  1533.                     pMD->PgmName=pU;
  1534.                     free(pMD->PgmDirectory);
  1535.                     strcpy(pU=malloc(strlen("")+1), "");
  1536.                     pMD->PgmDirectory=pU;
  1537.                     free(pMD->PgmInputs);
  1538.                     strcpy(pU=malloc(strlen("")+1), "");
  1539.                     pMD->Item=ENTRYEMPTY;
  1540.                     break;              /* Ensure we only test once, because each routine
  1541.                                            changes the pointers */
  1542.                     }
  1543.                 if(pMD->Item==ENTRYSUBMENU)
  1544.                 if((pMD->Submenu)->Item==ENTRYEMPTY)
  1545.                     {                   /* If it is an empty Submenu so also remove the
  1546.                                            first item in the Submenu */
  1547.                                         /* Remove the Submenu and the empty first item
  1548.                                            from the Popup-Menu */
  1549.                     SetPopupMenu(MM_DELETEITEM, MPFROMP(pMD), MPFROMLONG(pMD->id));
  1550.                     free((pMD->Submenu)->PgmTitle);
  1551.                     free((pMD->Submenu)->WindowTitle);
  1552.                     free((pMD->Submenu)->PgmName);
  1553.                     free((pMD->Submenu)->PgmDirectory);
  1554.                     free((pMD->Submenu)->PgmInputs);
  1555.                     free(pMD->Submenu);
  1556.                     if(((pMD->Back)->Submenu==pMD) && (pMD->Next==NULL))
  1557.                         {               /* If the previous item is a Submenu, this item is
  1558.                                            the first item of it. If none item follows, set
  1559.                                            this item to empty */
  1560.                         free(pMD->PgmTitle);
  1561.                         strcpy(pU=malloc(strlen("")+1), "");
  1562.                         pMD->PgmTitle=pU;
  1563.                         free(pMD->WindowTitle);
  1564.                         strcpy(pU=malloc(strlen("")+1), "");
  1565.                         pMD->WindowTitle=pU;
  1566.                         free(pMD->PgmName);
  1567.                         strcpy(pU=malloc(strlen("")+1), "");
  1568.                         pMD->PgmName=pU;
  1569.                         free(pMD->PgmDirectory);
  1570.                         strcpy(pU=malloc(strlen("")+1), "");
  1571.                         pMD->PgmDirectory=pU;
  1572.                         free(pMD->PgmInputs);
  1573.                         strcpy(pU=malloc(strlen("")+1), "");
  1574.                         pMD->Item=ENTRYEMPTY;
  1575.                         pMD->Submenu=NULL;
  1576.                         pMD->Next=NULL;
  1577.                         break;          /* Ensure we only test once, because each routine
  1578.                                            changes the pointers */
  1579.                         }
  1580.                     if(((pMD->Back)->Submenu==pMD) && (pMD->Next!=NULL))
  1581.                         {               /* If the previous item is a Submenu, this item ist
  1582.                                            the first item of it. If one item follows adjust
  1583.                                            the pointer to the current level of items */
  1584.                         pMenuData=pMD->Next;
  1585.                         (pMD->Back)->Submenu=pMD->Next;
  1586.                         if(pMD->Next!=NULL) (pMD->Next)->Back=pMD->Back;
  1587.                         free(pMD->PgmTitle);
  1588.                         free(pMD->WindowTitle);
  1589.                         free(pMD->PgmName);
  1590.                         free(pMD->PgmDirectory);
  1591.                         free(pMD->PgmInputs);
  1592.                         free(pMD);
  1593.                         break;          /* Ensure we only test once, because each routine
  1594.                                            changes the pointers */
  1595.                         }
  1596.                     if((pMD->Back)->Submenu!=pMD)
  1597.                         {               /* If this item isn't the first item of a Submenu */
  1598.                         (pMD->Back)->Next=pMD->Next;
  1599.                         if(pMD->Next!=NULL) (pMD->Next)->Back=pMD->Back;
  1600.                         free(pMD->PgmTitle);
  1601.                         free(pMD->WindowTitle);
  1602.                         free(pMD->PgmName);
  1603.                         free(pMD->PgmDirectory);
  1604.                         free(pMD->PgmInputs);
  1605.                         free(pMD);
  1606.                         break;          /* Ensure we only test once, because each routine
  1607.                                            changes the pointers */
  1608.                         }
  1609.                     }
  1610.                 if((pMD->Item==ENTRYMENUITEM) || pMD->Item==ENTRYCONTROL)
  1611.                     {                   /* If it is a Menuitem or Control just remove it completly */
  1612.                                         /* Remove the item from the Popup-Menu */
  1613.                     SetPopupMenu(MM_DELETEITEM, MPFROMP(pMD), MPFROMLONG(pMD->id));
  1614.                     if(((pMD->Back)->Submenu==pMD) && (pMD->Next==NULL))
  1615.                         {               /* If the previous item is a Submenu, this item is
  1616.                                            the first item of it. If none item follows, set
  1617.                                            this item to empty */
  1618.                         free(pMD->PgmTitle);
  1619.                         strcpy(pU=malloc(strlen("")+1), "");
  1620.                         pMD->PgmTitle=pU;
  1621.                         free(pMD->WindowTitle);
  1622.                         strcpy(pU=malloc(strlen("")+1), "");
  1623.                         pMD->WindowTitle=pU;
  1624.                         free(pMD->PgmName);
  1625.                         strcpy(pU=malloc(strlen("")+1), "");
  1626.                         pMD->PgmName=pU;
  1627.                         free(pMD->PgmDirectory);
  1628.                         strcpy(pU=malloc(strlen("")+1), "");
  1629.                         pMD->PgmDirectory=pU;
  1630.                         free(pMD->PgmInputs);
  1631.                         strcpy(pU=malloc(strlen("")+1), "");
  1632.                         pMD->Item=ENTRYEMPTY;
  1633.                         pMD->Submenu=NULL;
  1634.                         pMD->Next=NULL;
  1635.                         break;          /* Ensure we only test once, because each routine
  1636.                                            changes the pointers */
  1637.                         }
  1638.                     if(((pMD->Back)->Submenu==pMD) && (pMD->Next!=NULL))
  1639.                         {               /* If the previous item is a Submenu, this item ist
  1640.                                            the first item of it. If one item follows adjust
  1641.                                            the pointer to the current level of items */
  1642.                         pMenuData=pMD->Next;
  1643.                         (pMD->Back)->Submenu=pMD->Next;
  1644.                         if(pMD->Next!=NULL) (pMD->Next)->Back=pMD->Back;
  1645.                         free(pMD->PgmTitle);
  1646.                         free(pMD->WindowTitle);
  1647.                         free(pMD->PgmName);
  1648.                         free(pMD->PgmDirectory);
  1649.                         free(pMD->PgmInputs);
  1650.                         free(pMD);
  1651.                         break;          /* Ensure we only test once, because each routine
  1652.                                            changes the pointers */
  1653.                         }
  1654.                     if((pMD->Back)->Submenu!=pMD)
  1655.                         {               /* If this item isn't the first item of a Submenu */
  1656.                         (pMD->Back)->Next=pMD->Next;
  1657.                         if(pMD->Next!=NULL) (pMD->Next)->Back=pMD->Back;
  1658.                         free(pMD->PgmTitle);
  1659.                         free(pMD->WindowTitle);
  1660.                         free(pMD->PgmName);
  1661.                         free(pMD->PgmDirectory);
  1662.                         free(pMD->PgmInputs);
  1663.                         free(pMD);
  1664.                         break;          /* Ensure we only test once, because each routine
  1665.                                            changes the pointers */
  1666.                         }
  1667.                     }
  1668.                 }
  1669.             break;                      /* If we come here, we're trying to remove an not
  1670.                                            empty Submenu, but we also must exit the
  1671.                                            endless loop */
  1672.             }
  1673.                                         /* Initialize the listbox */
  1674.         WinSendMsg(hwndDlg, WM_LOADPOPUPMENU, MPFROMP(pMenuData), NULL);
  1675.         return((MRESULT)FALSE);         /* We have done everything */
  1676.         }
  1677.  
  1678. /*                                                                                      *\
  1679.  * The user selected to resort the current level of the menuentries. Load the dialog    *
  1680.  * and let the user resort the linked list of menues pointed to by pMenuData and to     *
  1681.  * resort the menuentries of the Popup-Menu.                                            *
  1682. \*                                                                                      */
  1683.     case CDID_RESORT:                   /* Load the resort dialog */
  1684.         {
  1685.         WinDismissDlg(hwndDlg, TRUE);   /* Clear up Configuration dialog */
  1686.         if(!WinDlgBox(                  /* Start Resort dialog box */
  1687.             HWND_DESKTOP,               /* DESKTOP is parent */
  1688.             HWND_DESKTOP,               /* DESKTOP is owner */
  1689.             RD_DialogProcedure,         /* Dialog procedure of Program Installation
  1690.                                            dialog */
  1691.             0,                          /* Ressource is .EXE file */
  1692.             RDID_RESORTDIALOG,          /* ID of Program Installation PC/2 dialog */
  1693.             0))                         /* No initialization data */
  1694.             GEN_ERR(hab, hwndFrame, hwndClient);
  1695.         if(!WinDlgBox(                  /* Now reload the Configuration dialog */
  1696.             HWND_DESKTOP,
  1697.             HWND_DESKTOP,
  1698.             CD_DialogProcedure,
  1699.             0,
  1700.             CDID_CONFIGDIALOG,
  1701.             0)) GEN_ERR(hab, hwndFrame, hwndClient);
  1702.         }
  1703.         break;
  1704.  
  1705.     case DID_OK:                        /* Enter key pressed */
  1706.                                         /* Save the changes */
  1707.         WinSendMsg(hwndDlg, WM_SAVEPOPUPMENU, NULL, NULL);
  1708.         DialogResult=DID_OK;            /* Dialog terminated with DID_OK */
  1709.         break;
  1710.  
  1711.     case DID_CANCEL:                    /* Escape or Cancel pressed */
  1712.         DialogResult=DID_CANCEL;        /* Dialog terminated with DID_CANCEL */
  1713.         break;
  1714.  
  1715.     default:
  1716.         return(WinDefDlgProc(hwndDlg, msg, mp1, mp2));
  1717.     }
  1718.     WinDismissDlg(hwndDlg, TRUE);       /* Clear up dialog */
  1719.     break;
  1720.  
  1721. default:                                /* Default window procedure must be called */
  1722.     return(WinDefDlgProc(hwndDlg, msg, mp1, mp2));
  1723. }
  1724. return((MRESULT)FALSE);                 /* We have handled the message */
  1725. }
  1726.  
  1727.